package com.soft.base.misc;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import sun.awt.image.ToolkitImage;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
 * class
 *
 * @author user
 * @date 2020/06/05
 */
@Slf4j
public class SmartImage {

    @Getter
    @Setter
    private BufferedImage image;

    public static SmartImage make(String path) {
        SmartImage si = new SmartImage();
        si.load(path);
        return si;
    }

    public static SmartImage make(InputStream is) {
        SmartImage si = new SmartImage();
        si.load(is);
        return si;
    }

    public static SmartImage canvas(int width, int height) {
        SmartImage si = new SmartImage();
        si.image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        return si;
    }

    public SmartImage load(String path) {
        try {
            this.image = ImageIO.read(new FileInputStream(path));
        } catch (IOException e) {
            log.error("SmartImage.load", e);
        }
        return this;
    }

    public SmartImage load(InputStream is) {
        try {
            this.image = ImageIO.read(is);
        } catch (IOException e) {
            log.error("SmartImage.load", e);
        }
        return this;
    }

    public SmartImage resize(int width, int height) {
        ToolkitImage image = (ToolkitImage) this.image.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH);
        image.getWidth();
        this.image = image.getBufferedImage();
        return this;
    }

    public SmartImage insert(int x, int y, BufferedImage image) {
        Graphics g = this.image.getGraphics();
        g.drawImage(image, x, y, null);
        g.dispose();
        return this;
    }

    public SmartImage insert(int x, int y, SmartImage image) {
        Graphics g = this.image.getGraphics();
        g.drawImage(image.image, x, y, null);
        g.dispose();
        return this;
    }

    public static int colorChange(int colorRgba, double rate) {
        int newColor = 0;
        int size = 3;
        newColor = newColor | (0xFF000000 & colorRgba);
        for (int i = 0; i < size; i++) {
            int v = (colorRgba >> (i * 8)) & 0x000000FF;
            v *= rate;
            if (v > 255) {
                v = 255;
            } else if (v < 0) {
                v = 0;
            }
            newColor = newColor | (v << (i * 8));
        }
        return newColor;
    }

    public SmartImage borderSmoothMask(Shape shape, int width) {
        Graphics2D g = (Graphics2D) this.image.getGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        int sw = width * 2;
        int size = 2;
        for (int i = sw; i >= size; i -= size) {
            float pct = (float) (sw - i) / (sw - 1);
            if (pct < 0.1 || pct > 0.9) {
                continue;
            }
            int alpha = (int) (255f * pct);
            g.setColor(new Color(alpha, alpha, alpha, alpha));
            g.setStroke(new BasicStroke(i));
            g.draw(shape);
        }
        g.dispose();
        return this;
    }

    public SmartImage alpha() {
        BufferedImage newImage = new BufferedImage(this.image.getWidth(), this.image.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics g = newImage.getGraphics();
        g.drawImage(this.image, 0, 0, null);
        g.dispose();
        this.image = newImage;
        return this;
    }

    public byte[] getBytes() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ImageIO.write(this.image, "png", bos);
            return bos.toByteArray();
        } catch (IOException e) {
            log.error("SmartImage.getBytes", e);
        }
        return new byte[0];
    }
}
